﻿using Dapper;
using System;
using System.Data;
using System.Linq;
using Ayatta.Contract.Domain;
using System.Collections.Generic;

namespace Ayatta.Service.Extension
{
    public static class DapperExtension
    {
        public static IEnumerable<TFirst> Query<TFirst, TSecond, TKey>(this IDbConnection connection,SqlTemplate template, Func<TFirst, TKey> firstKey, Func<TSecond, TKey> secondKey, Action<TFirst, IEnumerable<TSecond>> addChildren)
        {
            using (var reader = connection.QueryMultiple(template.Sql, template.Param))
            {
                var first = reader.Read<TFirst>().ToList();
                var second = reader.Read<TSecond>().GroupBy(secondKey).ToDictionary(g => g.Key, g => g.AsEnumerable());

                foreach (var item in first)
                {
                    IEnumerable<TSecond> children;
                    if (second.TryGetValue(firstKey(item), out children))
                    {
                        addChildren(item, children);
                    }
                }
                return first;
            }
        }

        public static PagedList<T> PagedList<T>(this IDbConnection connection, SqlTemplate template) where T : IEntity
        {
            int count;
            var data = new List<T>();
            using (var reader = connection.QueryMultiple(template.Sql, template.Param))
            {
                count = reader.Read<int>().FirstOrDefault();
                if (count > 0)
                {
                    data = reader.Read<T>().ToList();
                }
            }
            return new PagedList<T> { Data = data, Total = count };
        }

        public static PagedList<TFirst> PagedList<TFirst, TSecond, TKey>(this IDbConnection connection, SqlTemplate template, Func<TFirst, TKey> firstKey, Func<TSecond, TKey> secondKey, Action<TFirst, IEnumerable<TSecond>> addChildren)
        {
            int count;
            var data = new List<TFirst>();
            var second = new List<TSecond>();
            using (connection.EnsureOpen())
            using (var reader = connection.QueryMultiple(template.Sql, template.Param))
            {
                count = reader.Read<int>().FirstOrDefault();
                if (count > 0)
                {
                    data = reader.Read<TFirst>().ToList();
                    second = reader.Read<TSecond>().ToList();
                }
            }
            var children = second.GroupBy(secondKey).ToDictionary(g => g.Key, g => g.AsEnumerable());

            foreach (var item in data)
            {
                IEnumerable<TSecond> temp;
                if (children.TryGetValue(firstKey(item), out temp))
                {
                    addChildren(item, temp);
                }
            }
            return new PagedList<TFirst>(data, count);
        }
    }
}